//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#ifndef __AUDIOCARD_H__
#define __AUDIOCARD_H__

#include <elaaudio.h>

//#define DEBUG_AUDIO
#ifdef DEBUG_AUDIO
#define DBGOUT(x) (x)
#else
#define DBGOUT(x)
#define DBGCHAR(x)
#endif

#define AUDIO_BUFSIZE 0x1000
#define AUDIO_BUFCNT  16

#define MAX_WAIT_TIME 800 // Max time (tick) to wait for recording,tick=10 ms


// Definitions for DMA control
#define DMA_MAP_VALID_MASK  (0x1U << 7)  // Request is mapped to a valid channel indicated by DRCMRx(3:0)

#define DCSR_BUSERRINTR     (0x1U << 0)  // Bus error status bit
#define DCSR_STARTINTR      (0x1U << 1)  // Descriptor fetch status
#define DCSR_ENDINTR        (0x1U << 2)  // finish status
#define DCSR_STOPINTR       (0x1U << 3)  // stopped status
#define DCSR_REQPEND        (0x1U << 8)  // Request Pending (read-only)
#define DCSR_STARTIRQEN     (0x1U << 21) // Enable the start interrupt (when the descriptor is loaded)
#define DCSR_EORSTOPEN       (0x1U << 26) //
#define DCSR_STOPIRQEN       (0x1U << 29) // Enable the stopped interrupt (when the descriptor is done)
#define DCSR_NOFETCH        (0x1U << 30) // Descriptor fetch mode, 0 = fetch
#define DCSR_RUN            (0x1U << 31) // run, 1=start


#define IRQ_DMAC 25

#define BITS_8_TO_16(x)      ((UINT16)(((LONG) ((UINT8) (x) - 128) ) << 8))
#define BITS_16_TO_8(x)      ((BYTE) (((x) >> 8) + 128))

// AudioInital flags
#define AUDIO_ALLOCBUFFER   0x1
#define AUDIO_OPENHARDWARE  0x2

// Audio channel flags
#define AUDIO_DSP_PLAYING       0x1
#define AUDIO_DSP_RECORDING     0x2
#define AUDIO_HAND_FREEING      0x4
#define AUDIO_CALL_RECORDING    0x8
#define AUDIO_USE_SPEAKER       0x10
#define AUDIO_USE_HEADSET       0x20
#define AUDIO_PHONE_CALLING     0x40
#define AUDIO_BT_CALLING        0x80
#define AUDIO_USE_MAINMIC       0x100
#define AUDIO_USE_AUXMIC        0x200
#define AUDIO_MUTE              0x80000000 // Mute bit

#define AUDIO_MUTE_ALL  (AUDIO_MUTE | AUDIO_USE_SPEAKER | AUDIO_USE_HEADSET)

typedef enum {
    WAVEDIR_NOTPREPARED = 0,
    WAVEDIR_PLAYING,
    WAVEDIR_RECORDING,
    WAVEDIR_RESERVED
} WAVEDIR;

typedef enum {
    STATUS_INITIAL = 0,
    STATUS_NORMAL,
    STATUS_BUFFER_FULL,
    STATUS_BUFFER_EMPTY,
    STATUS_RESERVED
} AUDIOSTATUS;

typedef enum {
    WAVEINSOURCE_MAINMIC = 0,
    WAVEINSOURCE_AUXMIC,
    WAVEINSOURCE_LINE1,
    WAVEINSOURCE_LINE2,
    WAVEINSOURCE_LINEALL,
    WAVEINSOURCE_RESERVED
} WAVEINSOURCE;

#define VOLUMETYPE_SPEAKER      0
#define VOLUMETYPE_HEADSET      1
#define VOLUMETYPE_MONO         2
#define VOLUMETYPE_MIC          3
#define VOLUMETYPE_DACGAIN      4

#define CODEC_I2S_PLAYING      0x0001 // Open playing for AC97 codec
#define CODEC_I2S_RECORDING    0x0002 // Open recording for AC97 codec

#define SPEAKER_OPEN         0x0001 // Open or close speaker
#define SPEAKER_NEED_INITIAL 0x0002 // Need initialize speaker

#define HEADSET_OPEN         0x0001 // Open or close headset
#define HEADSET_NEED_INITIAL 0x0002 // Need initialize headset
#define HEADSET_PLUG         0x0004 // Whether the headset is plugged
#define HEADSET_PLUG_ISR     0x0008 // The headset make an ISR
typedef struct {
        Address bufVirt;
        Address bufPhys;
        Address descVirt;
        Address descPhys;
        BOOL bDmaInProgress;
        BOOL nBits;
        UINT nChannels;
        UINT nRate;
        UINT nFillingBufPos;
        UINT nFillingBufIdx;
        UINT nTransBufIdx;
        UINT nBufCnt;

        WAVEDIR waveDir;
        AUDIOSTATUS status;
        WAVEINSOURCE waveInSource;
        UINT codecStatus;
        UINT speakerStatus;
        UINT headsetStatus;

        // Volume
        BYTE volLeftOut;
        BYTE volRightOut;
        BYTE volLeftIn; // Reserved
        BYTE volRightIn; // Reserved

        int dmaChIn;
        int dmaChOut;

        void (*funcWriteCopy)(BYTE *pDes, BYTE *pSrc, UINT cnt);
        void (*funcReadCopy)(BYTE *pDes, BYTE *pSrc, UINT cnt);
} AudioContext;

ECode Audio_Create(AudioContext *pCxt);
ECode Audio_Initial(AudioContext *pCxt, WAVEDIR dir, ULONG flag);
ECode AudioOut_Write( AudioContext *pCxt,
        void *pData, UINT dataLen, UINT * pWritten);
ECode AudioIn_Read( AudioContext *pCxt,
        void *pData, UINT dataLen, UINT * pRead);
ECode Audio_FlushBuffer(AudioContext *pCxt);
ECode Audio_GetState(AudioContext *pCxt, Audio_Status *pStatus);
void Audio_Reset(AudioContext *pCxt);
void Audio_Close(AudioContext *pCxt, BOOL bFreeBuf);

ECode Ac97_Read(UCHAR Offset, USHORT * Data);
ECode  Ac97_Write(UCHAR Offset, USHORT  Data);
void Ac97_Reset(AudioContext *pCxt);

void Codec_SelectAudioInChannel(AudioContext *pCxt, int channel);
void Codec_SetGpios(AudioContext *pCxt);
ECode Codec_Init(AudioContext *pCxt);
ECode Codec_SetSampleRate(UINT rate, WAVEDIR dir);
ECode Codec_SetAudioOutVolume(AudioContext *pCxt, BYTE left, BYTE right);
ECode Codec_SetVolume(AudioContext *pCxt, BYTE left, BYTE right, UINT volType);
void Codec_OpenAmplifier(BOOL bOpen);
ECode Codec_InitHeadset(AudioContext *pCxt);
ECode Codec_SetAudioInSource(AudioContext *pCxt, WAVEINSOURCE source);
void Codec_Open(AudioContext *pCxt, WAVEDIR dir);
void Codec_Close(AudioContext *pCxt);

#if (_TEST_TYPE == 41)      /* Test for Runtime of ISR */
void SetOutIsrTime(/* [out] */ EzByteBuf ebbOutData);
void SetRcvIsrTime(/* [out] */ EzByteBuf ebbOutData);
#endif //_TEST_TYPE == 41

#endif//__AUDIOCARD_H__
